﻿using AutoMapper;
using EmployeesManager.Models;
using EmployeesManager.Poco;
using System;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using EmployeesManagerDataAccessContracts;

namespace EmployeesManager.Controllers
{
    public class EmployeesController : ApiController
    {
        private IRepository<Employee> _empRepo;
        public EmployeesController(IRepository<Employee> empRepo)
        {
            _empRepo = empRepo;
        }
        // GET api/Employees
        public IEnumerable<EmployeeForm> GetEmployees()
        {
            try
            {
                var employees = Mapper.Map<IEnumerable<Employee>, IEnumerable<EmployeeForm>>(_empRepo.Entities.ToList());
                return employees;
            }
            catch (Exception exception)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, exception.Message + ((exception.InnerException == null) ? "" : exception.InnerException.Message)));
            }
        }

        // GET api/Employees/5
        public EmployeeForm GetEmployee(int id)
        {
            Employee employee = _empRepo.Entities.FirstOrDefault(x => x.Id == id);
            var emp = Mapper.Map<Employee, EmployeeForm>(employee);
            if (employee == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            return emp;
        }

        // PUT api/Employees/5
        public HttpResponseMessage PutEmployee(int id, EmployeeForm employee)
        {
            employee.Id = id;
            if (!ModelState.IsValid)
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);

            var emp = Mapper.Map<EmployeeForm, Employee>(employee);
            if (_empRepo.Entities.Any(x => x.Id == id))
                _empRepo.Save(emp);
            else
                return Request.CreateResponse(HttpStatusCode.NotFound);

            return Request.CreateResponse(HttpStatusCode.OK, Mapper.Map<Employee, EmployeeForm>(emp));
        }

        // POST api/Employees
        public HttpResponseMessage PostEmployee(EmployeeForm employee)
        {
            ModelState.Remove("employee.Id");
            var emp = Mapper.Map<EmployeeForm, Employee>(employee);
            if (!ModelState.IsValid)
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);

            try
            {
                _empRepo.Save(emp);
            }
            catch (Exception exception)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, exception.Message));
            }
            employee = Mapper.Map<Employee, EmployeeForm>(emp);
            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, employee);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = employee.Id }));
            return response;
        }

        // DELETE api/Employees/5
        public HttpResponseMessage DeleteEmployee(int id)
        {
            var employee = _empRepo.Entities.FirstOrDefault(x => x.Id == id);
            if (employee == null)
                return Request.CreateResponse(HttpStatusCode.NotFound);

            try
            {
                _empRepo.Delete(id);
            }
            catch (DbUpdateConcurrencyException)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
            catch (DbUpdateException)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, "Can not delete this Employee because he is a manager of other employee(s)"));
            }
            catch (Exception exception)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, exception.Message));
            }

            return Request.CreateResponse(HttpStatusCode.Accepted, employee);
        }
    }
}